﻿using System;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.Linq;
using System.Windows;
using System.Windows.Controls;

namespace Waaahsabi.Controls.DWM
{
	[TemplateVisualStateAttribute(Name = "Idle", GroupName = "Default")]
	[TemplateVisualStateAttribute(Name = "StartMenuOn", GroupName = "Default")]
	public class Taskbar : Control
	{
		private Button _btnMain;
		private StackPanel _stkButtonList;

		#region Dependency Properties

		#region ClientFeatures
		public static readonly DependencyProperty ClientFeaturesProperty =
			DependencyProperty.Register
				(
				"ClientFeatures",
				typeof(ObservableCollection<StartMenuProgramGroupItem>),
				typeof(Taskbar),
				new PropertyMetadata(null)
				);

		public ObservableCollection<StartMenuProgramGroupItem> ClientFeatures
		{
			get { return (ObservableCollection<StartMenuProgramGroupItem>)GetValue(ClientFeaturesProperty); }
			set { SetValue(ClientFeaturesProperty, value); }
		}
		#endregion

		#region StartMenuGroups
		public static readonly DependencyProperty StartMenuGroupsProperty =
		DependencyProperty.Register
			(
			"StartMenuGroups",
			typeof(ObservableCollection<StartMenuProgramGroup>),
			typeof(Taskbar),
			new PropertyMetadata(null)
			);

		public ObservableCollection<StartMenuProgramGroup> StartMenuGroups
		{
			get { return (ObservableCollection<StartMenuProgramGroup>)GetValue(StartMenuGroupsProperty); }
			set { SetValue(StartMenuGroupsProperty, value); }
		}
		#endregion

		#region TaskBarItems
		public static readonly DependencyProperty ItemsProperty =
			DependencyProperty.Register
				(
					"Items",
					typeof (ObservableCollection<TaskBarItem>),
					typeof (Taskbar),
					new PropertyMetadata(new ObservableCollection<TaskBarItem>{new TaskBarItem {ItemId = Guid.Empty, ItemName = "Loooooooooooong item name"}})
				);

		public ObservableCollection<TaskBarItem> Items
		{
			get { return (ObservableCollection<TaskBarItem>)GetValue(ItemsProperty); }
			set { SetValue(ItemsProperty, value); }
		}
		#endregion

		#region StartMenu
		private static readonly DependencyProperty StartMenuProperty =
		DependencyProperty.Register
			(
			"StartMenu",
			typeof(StartMenu),
			typeof(Taskbar),
			new PropertyMetadata(null)
			);

		private StartMenu StartMenu
		{
			get { return (StartMenu)GetValue(StartMenuProperty); }
			set { SetValue(StartMenuProperty, value); }
		}
		#endregion

		#region StatusItems DependencyProperty
		public static readonly DependencyProperty StatusItemsProperty =
		DependencyProperty.Register
			(
			"StatusItems",
			typeof(ObservableCollection<TraceViewItem>),
			typeof(Taskbar),
			new PropertyMetadata(null)
			);

		public ObservableCollection<TraceViewItem> StatusItems
		{
			get { return (ObservableCollection<TraceViewItem>)GetValue(StatusItemsProperty); }
			set { SetValue(StatusItemsProperty, value); }
		}
		#endregion

		#region ClientIP DependencyProperty
		public static readonly DependencyProperty ClientIPProperty =
		DependencyProperty.Register
			(
			"ClientIP",
			typeof(string),
			typeof(Taskbar),
			new PropertyMetadata(null)
			);

		public string ClientIP
		{
			get { return (string)GetValue(ClientIPProperty); }
			set { SetValue(ClientIPProperty, value); }
		}
		#endregion


		#endregion

		public event EventHandler MainButtonClicked;
		public event EventHandler<TaskBarEventArgs> ItemClicked;
		public event EventHandler StartMenuCloseButtonClicked;
		public event EventHandler<ProgramItemExecuteArgs> StartMenuProgramExecuted;
		private bool _startMenuVisible;

		public Taskbar()
		{
			DefaultStyleKey = typeof(Taskbar);
			Items = new ObservableCollection<TaskBarItem>();
			Items.CollectionChanged += ItemsCollectionChanged;
			ClientFeatures = new ObservableCollection<StartMenuProgramGroupItem>();
			ClientFeatures.CollectionChanged += ClientFeaturesCollectionChanged;
			StartMenuGroups = new ObservableCollection<StartMenuProgramGroup>();
			StartMenuGroups.CollectionChanged += StartMenuGroupsCollectionChanged;
			StatusItems = new ObservableCollection<TraceViewItem>();
		}

		private void StartMenuGroupsCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
		{
			if (e.Action == NotifyCollectionChangedAction.Add)
			{
				foreach (StartMenuProgramGroup grp in e.NewItems)
					foreach (StartMenuProgramGroupItem item in grp.Items)
						item.Click += StartMenuProgramExecuteRequested;
			}
		}

		private void ClientFeaturesCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
		{
			if (e.Action == NotifyCollectionChangedAction.Add)
			{
				foreach (StartMenuProgramGroupItem item in e.NewItems)
					item.Click += StartMenuProgramExecuteRequested;
			}
		}

		private void ItemsCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
		{
			if(e.Action == NotifyCollectionChangedAction.Add)
			{
				foreach(TaskBarItem i in e.NewItems)
				{
					TaskBarButton btn = new TaskBarButton();
					btn.WindowId = i.ItemId;
					//if (i.ItemName.Length >= 10)
					//{
					//    btn.Content = i.ItemName.Substring(0, 7);
					//        btn.Content += "...";
					//}
					//else
						btn.Content = i.ItemName;
					btn.ToolTipText = i.ItemName;

					btn.Click += delegate
					{
						if (ItemClicked != null)
// ReSharper disable AccessToModifiedClosure
							ItemClicked(this, new TaskBarEventArgs {Item = i});
// ReSharper restore AccessToModifiedClosure
					};
					i.Button = btn;
					if (_stkButtonList != null)
						_stkButtonList.Children.Add(btn);
					btn.Margin = new Thickness(0, 0, -16, 5);
				}
			}
			if(e.Action == NotifyCollectionChangedAction.Remove)
			{
				foreach(TaskBarItem i in e.OldItems)
				{
					if (_stkButtonList != null)
					{
						TaskBarButton btn = (from it in _stkButtonList.Children.OfType<TaskBarButton>() where it.WindowId == i.ItemId select it).FirstOrDefault();
						if(btn == null)
							continue;
						_stkButtonList.Children.Remove(btn);
					}
				}
			}
		}

		public override void OnApplyTemplate()
		{
			base.OnApplyTemplate();
			_stkButtonList = GetTemplateChild("stkButtonList") as StackPanel;
			foreach (TaskBarItem i in Items)
				_stkButtonList.Children.Add(i.Button);

			_btnMain = GetTemplateChild("btnMain") as Button;
			if(_btnMain != null)
			{
				_btnMain.Click += (s, e) =>
				{
					if (!_startMenuVisible)
					{
						VisualStateManager.GoToState(this, "StartMenuOn", true);
						_startMenuVisible = true;
						if (MainButtonClicked != null)
							MainButtonClicked(this, null);
					}
					else
					{
						VisualStateManager.GoToState(this, "Idle", true);
						_startMenuVisible = false;
					}
				};
			}
			StartMenu = GetTemplateChild("startMenu") as StartMenu;

			if(StartMenu != null)
			{
				StartMenu.ProgramExecuteRequested += StartMenuProgramExecuteRequested;
				StartMenu.ClientFeatures = ClientFeatures;
				StartMenu.Groups = StartMenuGroups;
				StartMenu.CloseButtonClicked += (s, e) =>
				{
					if (StartMenuCloseButtonClicked != null) StartMenuCloseButtonClicked(this, null);
				};
			}
		}

		private void StartMenuProgramExecuteRequested(object sender, ProgramItemExecuteArgs e)
		{
			VisualStateManager.GoToState(this, "Idle", true);
			_startMenuVisible = false;
			if (StartMenuProgramExecuted != null)
				StartMenuProgramExecuted(this, e);
		}

		public void ShowStartMenu()
		{
			_startMenuVisible = true;
			VisualStateManager.GoToState(this, "StartMenuOn", true);
		}

		public void HideStartMenu()
		{
			_startMenuVisible = false;
			VisualStateManager.GoToState(this, "Idle", true);
		}
	}
}
